package spring.cloud.tasks.tasks_assign_manager.schedule;

import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import spring.cloud.tasks.common.cron_expression.CronExpression;
import spring.cloud.tasks.common.cron_expression.DateUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 进行判断什么时候开始进行运行
 */
@Setter
@Getter
public class CronExpressionContext {
    public static final String ENABLE = "Y";
    public static final String DISENABLE = "N";
    //
    private final String taskId;
    private String taskType;
    private volatile String enable = DISENABLE;
    //
    private volatile CronExpression cronExpression;
    /**
     * 提前进行预分配时间:单位分钟
     */
    private volatile Integer preAssignMinutes;
    //
    private volatile Date computeNextFireTimeMarkDate = new Date(0);//init
    private volatile List<TaskPreAssignTimePoint> taskPreAssignTimePointList = new ArrayList<TaskPreAssignTimePoint>();
    //
    private volatile Date lastPreAssignDate;
    private volatile Date lastRealPreAssignDate;
    //
    private volatile boolean rightNowRun = false;

    public CronExpressionContext(String taskId) {
        this.taskId = taskId;
    }

    public void computeNextFireTime(@NonNull String cronExpression, String pauseDatePeriod, String pauseTimePeriod, Integer preAssignMinutes) {
        if (preAssignMinutes == null || preAssignMinutes < 1) {
            preAssignMinutes = 1;
        }
        this.cronExpression = new CronExpression(cronExpression, pauseDatePeriod, pauseTimePeriod);
        this.preAssignMinutes = preAssignMinutes;
        computeNextFireTime();
    }

    /**
     * 计算出来的日期对象不一定准确
     */
    public void computeNextFireTime() {
        //
        List<TaskPreAssignTimePoint> taskPreAssignTimePointList = new ArrayList<TaskPreAssignTimePoint>();
        Date nowDate = new Date();
        Date startDate = new Date(nowDate.getTime() - DateUtils.HOUR * 2);//2和小时以前
        while (true) {
            Date nextFireTime = this.cronExpression.getFireTimeAfter(startDate);
            TaskPreAssignTimePoint taskPreAssignTimePoint = new TaskPreAssignTimePoint();
            taskPreAssignTimePoint.setNextFireDate(nextFireTime);
            taskPreAssignTimePoint.setNextPreAssignDate(new Date(taskPreAssignTimePoint.getNextFireDate().getTime() - 1000 * 60 * preAssignMinutes.intValue()));
            taskPreAssignTimePointList.add(taskPreAssignTimePoint);
            //
            if (nextFireTime.getTime() > nowDate.getTime() + DateUtils.HOUR * 2) {//2和小时以后
                break;
            }
        }
        synchronized (this) {//引用对象不保证可见性
            this.taskPreAssignTimePointList = taskPreAssignTimePointList;//快速替换对象 那么不会出现执行的时间频率变化很大的情况出现
            this.computeNextFireTimeMarkDate = new Date();
        }
    }
}
